Best Practices > Use the state instead of handles to identify subscribed entities |
The handles returned from any EasyXXClient.SubscribeXXXX methods are only meant for use as input arguments to other methods that manipulate the existing subscriptions – such as EasyXXClient.ChangeXXXX or EasyXXClient.UnsubscribeXXXX.
If you need to identify the subscribed entities inside event handlers, use the ‘state’ argument that can be passed to EasyXXClient.SubscribeXXXX methods (or a State property on XXXXArguments objects). You can pass any type of object in the state, as it is of type System.Object (and then cast the System.Object back to the original type in the event handler).
Why shouldn’t the handles be used? There are multiple reasons for that:
All these disadvantages can simply be overcome by passing the application data needed into the SubscribeXXXX method as a state object, and then casting the State to the appropriate type and using directly inside the event handler.
Note that earlier versions passed the handle to your code in the event arguments, making it relatively easy to make a mistake of using them from inside the handler. This is no longer the case with the current version, and the likeliness of violating this best practice is therefore much lower. With extra effort, you might be able to somehow “stick” the handle into the event notification, possibly by back-filling the State property after the subscription was made. It is strongly recommended that you do not do that for the reasons explained above.
// This example shows how subscribe to changes of multiple items and display each change, identifying the different // subscriptions by an integer. using System; using System.Threading; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeMultipleItems { public static void StateAsInteger() { // Instantiate the client object. using (var client = new EasyDAClient()) { // Hook events client.ItemChanged += client_StateAsInteger_ItemChanged; Console.WriteLine("Subscribing..."); int[] handleArray = client.SubscribeMultipleItems(new[] { new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, state: 1), // An integer we have chosen to identify the subscription new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, state: 2), // An integer we have chosen to identify the subscription new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, state: 3), // An integer we have chosen to identify the subscription new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, state: 4) // An integer we have chosen to identify the subscription }); for (int i = 0; i < handleArray.Length; i++) Console.WriteLine($"handleArray[{i}]: {handleArray[i]}"); Console.WriteLine("Processing item changed events for 10 seconds..."); Thread.Sleep(10 * 1000); Console.WriteLine("Unsubscribing..."); } Console.WriteLine("Waiting for 5 seconds..."); Thread.Sleep(5 * 1000); Console.WriteLine("Finished."); } // Item changed event handler static void client_StateAsInteger_ItemChanged(object sender, EasyDAItemChangedEventArgs eventArgs) { // Obtain the integer state we have passed in. var stateAsInteger = (int)eventArgs.Arguments.State; // Display the data if (eventArgs.Succeeded) Console.WriteLine($"{stateAsInteger}: {eventArgs.Vtq}"); else Console.WriteLine($"{stateAsInteger} *** Failure: {eventArgs.ErrorMessageBrief}"); } } }
# This example shows how subscribe to changes of multiple items and display each change, identifying the different # subscriptions by an integer. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.DataAccess import * from OpcLabs.EasyOpc.DataAccess.OperationModel import * # Item changed event handler. def itemChanged(sender, eventArgs): # Obtain the integer state we have passed in. stateAsInteger = int(eventArgs.Arguments.State) if eventArgs.Succeeded: print(stateAsInteger, ': ', eventArgs.Vtq, sep='') else: print(stateAsInteger, ' *** Failure: ', eventArgs.ErrorMessageBrief, sep='') # Instantiate the client object. client = EasyDAClient() # Hook events. client.ItemChanged += itemChanged print('Subscribing item changes...') handleArray = IEasyDAClientExtension.SubscribeMultipleItems(client, [ DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000, 1), # an integer we have chosen to identify the subscription DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000, 2), # an integer we have chosen to identify the subscription DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000, 3), # an integer we have chosen to identify the subscription DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000, 4), # an integer we have chosen to identify the subscription ]) for i in range(len(handleArray)): print('handleArray[', i, ']: ', handleArray[i], sep='') print('Processing item change notifications for 1 minute...') time.sleep(60) print('Unsubscribing all items...') client.UnsubscribeAllItems() client.ItemChanged -= itemChanged print('Finished.')
// This example shows how subscribe to changes of multiple items and display each change, identifying the different // subscriptions by an object. using System; using System.Threading; using OpcLabs.EasyOpc.DataAccess; using OpcLabs.EasyOpc.DataAccess.OperationModel; namespace DocExamples.DataAccess._EasyDAClient { partial class SubscribeMultipleItems { class CustomObject { public CustomObject(string name) { Name = name; } public string Name { get; } } public static void StateAsObject() { // Instantiate the client object. using (var client = new EasyDAClient()) { // Hook events client.ItemChanged += client_StateAsObject_ItemChanged; Console.WriteLine("Subscribing..."); int[] handleArray = client.SubscribeMultipleItems(new[] { new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, new CustomObject("First")), // A custom object that corresponds to the subscription new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, new CustomObject("Second")), // A custom object that corresponds to the subscription new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, new CustomObject("Third")), // A custom object that corresponds to the subscription new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, new CustomObject("Fourth")) // A custom object that corresponds to the subscription }); for (int i = 0; i < handleArray.Length; i++) Console.WriteLine($"handleArray[{i}]: {handleArray[i]}"); Console.WriteLine("Processing item changed events for 10 seconds..."); Thread.Sleep(10 * 1000); Console.WriteLine("Unsubscribing..."); } Console.WriteLine("Waiting for 5 seconds..."); Thread.Sleep(5 * 1000); Console.WriteLine("Finished."); } // Item changed event handler static void client_StateAsObject_ItemChanged(object sender, EasyDAItemChangedEventArgs eventArgs) { // Obtain the custom object we have passed in. var stateAsObject = (CustomObject)eventArgs.Arguments.State; // Display the data if (eventArgs.Succeeded) Console.WriteLine($"{stateAsObject.Name}: {eventArgs.Vtq}"); else Console.WriteLine($"{stateAsObject.Name} *** Failure: {eventArgs.ErrorMessageBrief}"); } } }
# This example shows how subscribe to changes of multiple items and display each change, identifying the different # subscriptions by an object. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.DataAccess import * from OpcLabs.EasyOpc.DataAccess.OperationModel import * class CustomObject(object): def __init__(self, name): self.name = name # Item changed event handler. def itemChanged(sender, eventArgs): # Obtain the custom object we have passed in. stateAsObject = eventArgs.Arguments.State if eventArgs.Succeeded: print(stateAsObject.name, ': ', eventArgs.Vtq, sep='') else: print(stateAsObject.name, ' *** Failure: ', eventArgs.ErrorMessageBrief, sep='') # Instantiate the client object. client = EasyDAClient() # Hook events. client.ItemChanged += itemChanged print('Subscribing item changes...') handleArray = IEasyDAClientExtension.SubscribeMultipleItems(client, [ DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000, CustomObject('First')), # a custom object that corresponds to the subscription DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000, CustomObject('Second')), # a custom object that corresponds to the subscription DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000, CustomObject('Third')), # a custom object that corresponds to the subscription DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000, CustomObject('Fourth')), # a custom object that corresponds to the subscription ]) for i in range(len(handleArray)): print('handleArray[', i, ']: ', handleArray[i], sep='') print('Processing item change notifications for 1 minute...') time.sleep(60) print('Unsubscribing all items...') client.UnsubscribeAllItems() client.ItemChanged -= itemChanged print('Finished.')
// This example shows how to subscribe to changes of multiple monitored items // and display each change, identifying the different subscriptions by an // integer. using System; using System.Threading; using OpcLabs.EasyOpc.UA; using OpcLabs.EasyOpc.UA.OperationModel; namespace UADocExamples._EasyUAClient { partial class SubscribeMultipleMonitoredItems { public static void StateAsInteger() { UAEndpointDescriptor endpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) // or "https://opcua.demo-this.com:51212/UA/SampleServer/" // Instantiate the client object and hook events. var client = new EasyUAClient(); client.DataChangeNotification += ClientOnDataChangeNotification_StateAsInteger; Console.WriteLine("Subscribing..."); int[] handleArray = client.SubscribeMultipleMonitoredItems(new[] { new EasyUAMonitoredItemArguments(null, endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10845", 1000) {State = 1}, // An integer we have chosen to identify the subscription new EasyUAMonitoredItemArguments(null, endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853", 1000) {State = 2}, // An integer we have chosen to identify the subscription new EasyUAMonitoredItemArguments(null, endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10855", 1000) {State = 3} // An integer we have chosen to identify the subscription }); for (int i = 0; i < handleArray.Length; i++) Console.WriteLine($"handleArray[{i}]: {handleArray[i]}"); Console.WriteLine("Processing monitored item changed events for 10 seconds..."); Thread.Sleep(10 * 1000); Console.WriteLine("Unsubscribing..."); client.UnsubscribeAllMonitoredItems(); Console.WriteLine("Waiting for 5 seconds..."); Thread.Sleep(5 * 1000); Console.WriteLine("Finished."); } static void ClientOnDataChangeNotification_StateAsInteger(object sender, EasyUADataChangeNotificationEventArgs eventArgs) { // Obtain the integer state we have passed in. var stateAsInteger = (int) eventArgs.Arguments.State; // Display the data. if (eventArgs.Succeeded) Console.WriteLine($"{stateAsInteger}: {eventArgs.AttributeData}"); else Console.WriteLine($"{stateAsInteger} *** Failure: {eventArgs.ErrorMessageBrief}"); } } }
# This example shows how to subscribe to changes of multiple monitored items # and display each change, identifying the different subscriptions by an # integer. #requires -Version 5.1 using namespace OpcLabs.EasyOpc.UA using namespace OpcLabs.EasyOpc.UA.OperationModel # The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows . Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll" Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll" [UAEndpointDescriptor]$endpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" # or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) # or "https://opcua.demo-this.com:51212/UA/SampleServer/" # Instantiate the client object. $client = New-Object EasyUAClient # Data change notification handler Register-ObjectEvent -InputObject $client -EventName DataChangeNotification -Action { # Obtain the integer state we have passed in. [int]$stateAsInteger = $EventArgs.Arguments.State # Display the data. if ($EventArgs.Succeeded) { Write-Host "$($stateAsinteger): $($EventArgs.AttributeData)" } else { Write-Host "$($stateAsinteger) *** Failure: $($EventArgs.ErrorMessageBrief)" } } Write-Host "Subscribing..." $handleArray = $client.SubscribeMultipleMonitoredItems(@( (New-Object UAMonitoredItemArguments( (New-Object UAAttributeArguments($endpointDescriptor, [UANodeDescriptor]"nsu=http://test.org/UA/Data/ ;i=10845")), 1000) -Property @{State = 1}), # An integer we have chosen to identify the subscription (New-Object UAMonitoredItemArguments( (New-Object UAAttributeArguments($endpointDescriptor, [UANodeDescriptor]"nsu=http://test.org/UA/Data/ ;i=10853")), 1000) -Property @{State = 2}), # An integer we have chosen to identify the subscription (New-Object UAMonitoredItemArguments( (New-Object UAAttributeArguments($endpointDescriptor, [UANodeDescriptor]"nsu=http://test.org/UA/Data/ ;i=10855")), 1000) -Property @{State = 3}) # An integer we have chosen to identify the subscription )) for ($i = 0; $i -lt $handleArray.Length; $i++) { Write-Host "handleArray[$($i)]: $($handleArray[$i])" } Write-Host Write-Host "Processing monitored item changed events for 10 seconds..." $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($stopwatch.Elapsed.TotalSeconds -lt 10) { Start-Sleep -Seconds 1 } Write-Host "Unsubscribing..." $client.UnsubscribeAllMonitoredItems() Write-Host "Waiting for 5 seconds..." Start-Sleep -Seconds 5 Write-Host "Finished."
# This example shows how to subscribe to changes of multiple monitored items # and display each change, identifying the different subscriptions by an # integer. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.UA import * from OpcLabs.EasyOpc.UA.OperationModel import * def dataChangeNotification(sender, eventArgs): # Obtain the integer state we have passed in. stateAsInteger = int(eventArgs.Arguments.State) # Display value. if eventArgs.Succeeded: print(stateAsInteger, ': ', eventArgs.AttributeData.Value, sep='') else: print(stateAsInteger, ' *** Failure: ', eventArgs.ErrorMessageBrief, sep='') endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer') # or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported) # or 'https://opcua.demo-this.com:51212/UA/SampleServer/' # Instantiate the client object and hook events. client = EasyUAClient() client.DataChangeNotification += dataChangeNotification print('Subscribing...') monitoredItemArguments1 = EasyUAMonitoredItemArguments( None, endpointDescriptor, UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10845'), UAMonitoringParameters(1000)) monitoredItemArguments1.State = 1 # an integer we have chosen to identify the subscription monitoredItemArguments2 = EasyUAMonitoredItemArguments( None, endpointDescriptor, UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'), UAMonitoringParameters(1000)) monitoredItemArguments2.State = 2 # an integer we have chosen to identify the subscription monitoredItemArguments3 = EasyUAMonitoredItemArguments( None, endpointDescriptor, UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10855'), UAMonitoringParameters(1000)) monitoredItemArguments3.State = 3 # an integer we have chosen to identify the subscription client.SubscribeMultipleMonitoredItems([ monitoredItemArguments1, monitoredItemArguments2, monitoredItemArguments3, ]) print('Processing data change events for 10 seconds...') time.sleep(10) print('Unsubscribing...') client.UnsubscribeAllMonitoredItems() print('Waiting for 5 seconds...') time.sleep(5) print('Finished.')
' This example shows how to subscribe to changes of multiple monitored items ' and display each change, identifying the different subscriptions by an ' integer. Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.OperationModel Namespace _EasyUAClient Partial Friend Class SubscribeMultipleMonitoredItems Public Shared Sub StateAsInteger() ' Define which server we will work with. Dim endpointDescriptor As UAEndpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) ' or "https://opcua.demo-this.com:51212/UA/SampleServer/" ' Instantiate the client object and hook events Dim client = New EasyUAClient() AddHandler client.DataChangeNotification, AddressOf ClientOnDataChangeNotification_StateAsInteger Console.WriteLine("Subscribing...") Dim handleArray() As Integer = client.SubscribeMultipleMonitoredItems(New EasyUAMonitoredItemArguments() _ { _ New EasyUAMonitoredItemArguments(Nothing, endpointDescriptor, _ "nsu=http://test.org/UA/Data/ ;i=10845", 1000) _ With {.State = 1}, _ New EasyUAMonitoredItemArguments(Nothing, endpointDescriptor, _ "nsu=http://test.org/UA/Data/ ;i=10853", 1000) _ With {.State = 2}, _ New EasyUAMonitoredItemArguments(Nothing, endpointDescriptor, _ "nsu=http://test.org/UA/Data/ ;i=10855", 1000) _ With {.State = 3} _ } _ ) ' An integer we have chosen to identify the subscription For i As Integer = 0 To handleArray.Length - 1 Console.WriteLine("handleArray[{0}]: {1}", i, handleArray(i)) Next i Console.WriteLine("Processing monitored item changed events for 10 seconds...") Threading.Thread.Sleep(10 * 1000) Console.WriteLine("Unsubscribing...") client.UnsubscribeAllMonitoredItems() Console.WriteLine("Waiting for 5 seconds...") Threading.Thread.Sleep(5 * 1000) Console.WriteLine("Finished.") End Sub Private Shared Sub ClientOnDataChangeNotification_StateAsInteger(ByVal sender As Object, ByVal eventArgs As EasyUADataChangeNotificationEventArgs) ' Obtain the integer state we have passed in. Dim stateAsInteger As Integer = CInt(eventArgs.Arguments.State) ' Display the data If eventArgs.Succeeded Then Console.WriteLine("{0}: {1}", stateAsInteger, eventArgs.AttributeData) Else Console.WriteLine("{0} *** Failure: {1}", stateAsInteger, eventArgs.ErrorMessageBrief) End If End Sub End Class End Namespace
// This example shows how to subscribe to changes of multiple monitored items // and display each change, identifying the different subscriptions by an // integer. type TIntegerClientEventHandlers124 = class procedure OnDataChangeNotification( ASender: TObject; sender: OleVariant; const eventArgs: _EasyUADataChangeNotificationEventArgs); end; procedure TIntegerClientEventHandlers124.OnDataChangeNotification( ASender: TObject; sender: OleVariant; const eventArgs: _EasyUADataChangeNotificationEventArgs); var stateAsInteger: Integer; begin // Obtain the integer state we have passed in. stateAsInteger := eventArgs.Arguments.State; if eventArgs.Succeeded then WriteLn(stateAsInteger, ': ', eventArgs.AttributeData.ToString) else WriteLn(stateAsInteger, ' *** Failure: ', eventArgs.ErrorMessageBrief); end; class procedure SubscribeMultipleMonitoredItems.StateAsInteger; var Arguments: OleVariant; Client: TEasyUAClient; ClientEventHandlers: TIntegerClientEventHandlers124; Handle: Cardinal; HandleArray: OleVariant; I: Cardinal; MonitoredItemArguments1, MonitoredItemArguments2, MonitoredItemArguments3: _EasyUAMonitoredItemArguments; MonitoringParameters: _UAMonitoringParameters; begin // Instantiate the client object and hook events Client := TEasyUAClient.Create(nil); ClientEventHandlers := TIntegerClientEventHandlers124.Create; Client.OnDataChangeNotification := ClientEventHandlers.OnDataChangeNotification; WriteLn('Subscribing...'); MonitoringParameters := CoUAMonitoringParameters.Create; MonitoringParameters.SamplingInterval := 1000; MonitoredItemArguments1 := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments1.EndpointDescriptor.UrlString := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; MonitoredItemArguments1.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10845'; MonitoredItemArguments1.MonitoringParameters := MonitoringParameters; MonitoredItemArguments1.SetState(1); // An integer we have chosen to identify the subscription MonitoredItemArguments2 := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments2.EndpointDescriptor.UrlString := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; MonitoredItemArguments2.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10853'; MonitoredItemArguments2.MonitoringParameters := MonitoringParameters; MonitoredItemArguments2.SetState(2); // An integer we have chosen to identify the subscription MonitoredItemArguments3 := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments3.EndpointDescriptor.UrlString := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; MonitoredItemArguments3.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10855'; MonitoredItemArguments3.MonitoringParameters := MonitoringParameters; MonitoredItemArguments3.SetState(3); // An integer we have chosen to identify the subscription Arguments := VarArrayCreate([0, 2], varVariant); Arguments[0] := MonitoredItemArguments1; Arguments[1] := MonitoredItemArguments2; Arguments[2] := MonitoredItemArguments3; TVarData(HandleArray).VType := varArray or varVariant; TVarData(HandleArray).VArray := PVarArray( Client.SubscribeMultipleMonitoredItems(Arguments)); for I := VarArrayLowBound(HandleArray, 1) to VarArrayHighBound(HandleArray, 1) do begin Handle := Cardinal(HandleArray[I]); WriteLn('HandleArray[', I, ']: ', Handle); end; WriteLn('Processing monitored item changed events for 10 seconds...'); PumpSleep(10*1000); WriteLn('Unsubscribing...'); Client.UnsubscribeAllMonitoredItems; WriteLn('Waiting for 5 seconds...'); Sleep(5*1000); WriteLn('Finished.'); VarClear(HandleArray); VarClear(Arguments); FreeAndNil(Client); FreeAndNil(ClientEventHandlers); end;
// This example shows how to subscribe to changes of multiple monitored items // and display each change, identifying the different subscriptions by an // integer. class ClientEvents { function DataChangeNotification($Sender, $E) { // Obtain the integer state we have passed in. $stateAsInteger = $E->Arguments->State; if ($E->Succeeded) printf("d: s\n", $stateAsInteger, $E->AttributeData); else printf("d *** Failures\n", $stateAsInteger, $E->ErrorMessageBrief); } } // Instantiate the client object and hook events $Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient"); $ClientEvents = new ClientEvents(); com_event_sink($Client, $ClientEvents, "DEasyUAClientEvents"); printf("Subscribing...\n"); $MonitoringParameters = new COM("OpcLabs.EasyOpc.UA.UAMonitoringParameters"); $MonitoringParameters->SamplingInterval = 1000; $MonitoredItemArguments1 = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments"); $MonitoredItemArguments1->EndpointDescriptor->UrlString = //"http://opcua.demo-this.com:51211/UA/SampleServer"; //"https://opcua.demo-this.com:51212/UA/SampleServer/"; "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; $MonitoredItemArguments1->NodeDescriptor->NodeId->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10845"; $MonitoredItemArguments1->MonitoringParameters = $MonitoringParameters; $MonitoredItemArguments1->SetState(1); // An integer we have chosen to identify the subscription $MonitoredItemArguments2 = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments"); $MonitoredItemArguments2->EndpointDescriptor->UrlString = //"http://opcua.demo-this.com:51211/UA/SampleServer"; //"https://opcua.demo-this.com:51212/UA/SampleServer/"; "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; $MonitoredItemArguments2->NodeDescriptor->NodeId->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853"; $MonitoredItemArguments2->MonitoringParameters = $MonitoringParameters; $MonitoredItemArguments2->SetState(2); // An integer we have chosen to identify the subscription $MonitoredItemArguments3 = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments"); $MonitoredItemArguments3->EndpointDescriptor->UrlString = //"http://opcua.demo-this.com:51211/UA/SampleServer"; //"https://opcua.demo-this.com:51212/UA/SampleServer/"; "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; $MonitoredItemArguments3->NodeDescriptor->NodeId->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10855"; $MonitoredItemArguments3->MonitoringParameters = $MonitoringParameters; $MonitoredItemArguments3->SetState(3); // An integer we have chosen to identify the subscription $arguments[0] = $MonitoredItemArguments1; $arguments[1] = $MonitoredItemArguments2; $arguments[2] = $MonitoredItemArguments3; $handleArray = $Client->SubscribeMultipleMonitoredItems($arguments); for ($i = 0; $i < count($handleArray); $i++) { printf("handleArray[d]d\n", $i, $handleArray[$i]); } printf("Processing monitored item changed events for 10 seconds...\n"); $startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 10); printf("Unsubscribing...\n"); $Client->UnsubscribeAllMonitoredItems; printf("Waiting for 5 seconds...\n"); $startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 5);
Rem This example shows how to subscribe to changes of multiple monitored items Rem and display each change, identifying the different subscriptions by an Rem integer. ' The client object, with events 'Public WithEvents Client6 As EasyUAClient Public Sub SubscribeMultipleMonitoredItems_StateAsInteger_Command_Click() OutputText = "" Set Client6 = New EasyUAClient OutputText = OutputText & "Subscribing..." & vbCrLf Dim MonitoringParameters As New UAMonitoringParameters MonitoringParameters.SamplingInterval = 1000 Dim MonitoredItemArguments1 As New EasyUAMonitoredItemArguments MonitoredItemArguments1.endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" MonitoredItemArguments1.nodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10845" Set MonitoredItemArguments1.MonitoringParameters = MonitoringParameters MonitoredItemArguments1.SetState 1 ' An integer we have chosen to identify the subscription Dim MonitoredItemArguments2 As New EasyUAMonitoredItemArguments MonitoredItemArguments2.endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" MonitoredItemArguments2.nodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10853" Set MonitoredItemArguments2.MonitoringParameters = MonitoringParameters MonitoredItemArguments2.SetState 2 ' An integer we have chosen to identify the subscription Dim MonitoredItemArguments3 As New EasyUAMonitoredItemArguments MonitoredItemArguments3.endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" MonitoredItemArguments3.nodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10855" Set MonitoredItemArguments3.MonitoringParameters = MonitoringParameters MonitoredItemArguments3.SetState 3 ' An integer we have chosen to identify the subscription Dim arguments(2) As Variant Set arguments(0) = MonitoredItemArguments1 Set arguments(1) = MonitoredItemArguments2 Set arguments(2) = MonitoredItemArguments3 Dim handleArray As Variant handleArray = Client6.SubscribeMultipleMonitoredItems(arguments) Dim i As Long: For i = LBound(handleArray) To UBound(handleArray) OutputText = OutputText & "handleArray(" & i & "): " & handleArray(i) & vbCrLf Next OutputText = OutputText & "Processing monitored item changed events for 10 seconds..." & vbCrLf Pause 10000 OutputText = OutputText & "Unsubscribing..." & vbCrLf Call Client6.UnsubscribeAllMonitoredItems OutputText = OutputText & "Waiting for 5 seconds..." & vbCrLf Pause 5000 Set Client2 = Nothing OutputText = OutputText & "Finished." & vbCrLf End Sub Public Sub Client6_DataChangeNotification(ByVal sender As Variant, ByVal eventArgs As EasyUADataChangeNotificationEventArgs) ' Obtain the integer state we have passed in. Dim stateAsInteger As Integer: stateAsInteger = eventArgs.arguments.State If eventArgs.Succeeded Then OutputText = OutputText & stateAsInteger & ": " & eventArgs.AttributeData & vbCrLf Else OutputText = OutputText & stateAsInteger & " *** Failure: " & eventArgs.ErrorMessageBrief & vbCrLf End If End Sub
// This example shows how to subscribe to changes of multiple monitored items // and display each change, identifying the different subscriptions by an // object. using System; using System.Threading; using OpcLabs.EasyOpc.UA; using OpcLabs.EasyOpc.UA.OperationModel; namespace UADocExamples._EasyUAClient { partial class SubscribeMultipleMonitoredItems { class CustomObject { public CustomObject(string name) { Name = name; } public string Name { get; } } public static void StateAsObject() { UAEndpointDescriptor endpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) // or "https://opcua.demo-this.com:51212/UA/SampleServer/" // Instantiate the client object and hook events var client = new EasyUAClient(); client.DataChangeNotification += ClientOnDataChangeNotification_StateAsObject; Console.WriteLine("Subscribing..."); int[] handleArray = client.SubscribeMultipleMonitoredItems(new[] { new EasyUAMonitoredItemArguments(null, endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10845", 1000) {State = new CustomObject("First")}, // A custom object that corresponds to the subscription new EasyUAMonitoredItemArguments(null, endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853", 1000) {State = new CustomObject("Second")}, // A custom object that corresponds to the subscription new EasyUAMonitoredItemArguments(null, endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10855", 1000) {State = new CustomObject("Third")}, // A custom object that corresponds to the subscription }); for (int i = 0; i < handleArray.Length; i++) Console.WriteLine($"handleArray[{i}]: {handleArray[i]}"); Console.WriteLine("Processing monitored item changed events for 10 seconds..."); Thread.Sleep(10 * 1000); Console.WriteLine("Unsubscribing..."); client.UnsubscribeAllMonitoredItems(); Console.WriteLine("Waiting for 5 seconds..."); Thread.Sleep(5 * 1000); Console.WriteLine("Finished."); } static void ClientOnDataChangeNotification_StateAsObject(object sender, EasyUADataChangeNotificationEventArgs eventArgs) { // Obtain the custom object we have passed in. var stateAsObject = (CustomObject) eventArgs.Arguments.State; // Display the data if (eventArgs.Succeeded) Console.WriteLine($"{stateAsObject.Name}: {eventArgs.AttributeData}"); else Console.WriteLine($"{stateAsObject.Name} *** Failure: {eventArgs.ErrorMessageBrief}"); } } }
# This example shows how to subscribe to changes of multiple monitored items # and display each change, identifying the different subscriptions by an # object. # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc import time # Import .NET namespaces. from OpcLabs.EasyOpc.UA import * from OpcLabs.EasyOpc.UA.OperationModel import * class CustomObject(object): def __init__(self, name): self.name = name def dataChangeNotification(sender, eventArgs): # Obtain the custom object we have passed in. stateAsObject = eventArgs.Arguments.State # Display value. if eventArgs.Succeeded: print(stateAsObject.name, ': ', eventArgs.AttributeData.Value, sep='') else: print(stateAsObject.name, ' *** Failure: ', eventArgs.ErrorMessageBrief, sep='') endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer') # or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported) # or 'https://opcua.demo-this.com:51212/UA/SampleServer/' # Instantiate the client object and hook events. client = EasyUAClient() client.DataChangeNotification += dataChangeNotification print('Subscribing...') monitoredItemArguments1 = EasyUAMonitoredItemArguments( None, endpointDescriptor, UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10845'), UAMonitoringParameters(1000)) monitoredItemArguments1.State = CustomObject('First') # a custom object that corresponds to the subscription monitoredItemArguments2 = EasyUAMonitoredItemArguments( None, endpointDescriptor, UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'), UAMonitoringParameters(1000)) monitoredItemArguments2.State = CustomObject('Second') # a custom object that corresponds to the subscription monitoredItemArguments3 = EasyUAMonitoredItemArguments( None, endpointDescriptor, UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10855'), UAMonitoringParameters(1000)) monitoredItemArguments3.State = CustomObject('Third') # a custom object that corresponds to the subscription client.SubscribeMultipleMonitoredItems([ monitoredItemArguments1, monitoredItemArguments2, monitoredItemArguments3, ]) print('Processing data change events for 10 seconds...') time.sleep(10) print('Unsubscribing...') client.UnsubscribeAllMonitoredItems() print('Waiting for 5 seconds...') time.sleep(5) print('Finished.')
' This example shows how to subscribe to changes of multiple monitored items ' and display each change, identifying the different subscriptions by an ' object. Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.OperationModel Namespace _EasyUAClient Partial Friend Class SubscribeMultipleMonitoredItems Class CustomObject Public Sub New(ByVal name As String) _Name = name End Sub Public ReadOnly Property Name As String Get Return _Name End Get End Property Private ReadOnly _Name As String End Class Public Shared Sub StateAsObject() ' Define which server we will work with. Dim endpointDescriptor As UAEndpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) ' or "https://opcua.demo-this.com:51212/UA/SampleServer/" ' Instantiate the client object and hook events Dim client = New EasyUAClient() AddHandler client.DataChangeNotification, AddressOf ClientOnDataChangeNotification_StateAsObject Console.WriteLine("Subscribing...") Dim handleArray() As Integer = client.SubscribeMultipleMonitoredItems(New EasyUAMonitoredItemArguments() _ { _ New EasyUAMonitoredItemArguments(Nothing, endpointDescriptor, _ "nsu=http://test.org/UA/Data/ ;i=10845", 1000) _ With {.State = New CustomObject("First")}, _ New EasyUAMonitoredItemArguments(Nothing, endpointDescriptor, _ "nsu=http://test.org/UA/Data/ ;i=10853", 1000) _ With {.State = New CustomObject("Second")}, _ New EasyUAMonitoredItemArguments(Nothing, endpointDescriptor, _ "nsu=http://test.org/UA/Data/ ;i=10855", 1000) _ With {.State = New CustomObject("Third")} _ } _ ) ' A custom object that corresponds to the subscription For i As Integer = 0 To handleArray.Length - 1 Console.WriteLine("handleArray[{0}]: {1}", i, handleArray(i)) Next i Console.WriteLine("Processing monitored item changed events for 10 seconds...") Threading.Thread.Sleep(10 * 1000) Console.WriteLine("Unsubscribing...") client.UnsubscribeAllMonitoredItems() Console.WriteLine("Waiting for 5 seconds...") Threading.Thread.Sleep(5 * 1000) Console.WriteLine("Finished.") End Sub Private Shared Sub ClientOnDataChangeNotification_StateAsObject(ByVal sender As Object, ByVal eventArgs As EasyUADataChangeNotificationEventArgs) ' Obtain the custom object we have passed in. Dim stateAsObject As CustomObject = CType(eventArgs.Arguments.State, CustomObject) ' Display the data If eventArgs.Succeeded Then Console.WriteLine("{0}: {1}", stateAsObject.Name, eventArgs.AttributeData) Else Console.WriteLine("{0} *** Failure: {1}", stateAsObject.Name, eventArgs.ErrorMessageBrief) End If End Sub End Class End Namespace
// This example shows how to subscribe to changes of multiple monitored items // and display each change, identifying the different subscriptions by an // object. type TCustomObject = class Name: string; constructor Create(name: string); end; constructor TCustomObject.Create(name: string); begin Self.Name := name; end; type TObjectClientEventHandlers125 = class procedure OnDataChangeNotification( ASender: TObject; sender: OleVariant; const eventArgs: _EasyUADataChangeNotificationEventArgs); end; procedure TObjectClientEventHandlers125.OnDataChangeNotification( ASender: TObject; sender: OleVariant; const eventArgs: _EasyUADataChangeNotificationEventArgs); var stateAsObject: TCustomObject; begin // Obtain the custom object we have passed in. stateAsObject := TCustomObject(INT_PTR(eventArgs.Arguments.State)); // Display the data if eventArgs.Succeeded then WriteLn(stateAsObject.Name, ': ', eventArgs.AttributeData.ToString) else WriteLn(stateAsObject.Name, ' *** Failure: ', eventArgs.ErrorMessageBrief); end; class procedure SubscribeMultipleMonitoredItems.StateAsObject; var Arguments: OleVariant; Client: TEasyUAClient; ClientEventHandlers: TObjectClientEventHandlers125; Handle: Cardinal; HandleArray: OleVariant; I: Cardinal; MonitoredItemArguments1, MonitoredItemArguments2, MonitoredItemArguments3: _EasyUAMonitoredItemArguments; MonitoringParameters: _UAMonitoringParameters; CustomObject1, CustomObject2, CustomObject3: TCustomObject; begin CustomObject1 := TCustomObject.Create('First'); CustomObject2 := TCustomObject.Create('Second'); CustomObject3 := TCustomObject.Create('Third'); // Instantiate the client object and hook events Client := TEasyUAClient.Create(nil); ClientEventHandlers := TObjectClientEventHandlers125.Create; Client.OnDataChangeNotification := ClientEventHandlers.OnDataChangeNotification; WriteLn('Subscribing...'); MonitoringParameters := CoUAMonitoringParameters.Create; MonitoringParameters.SamplingInterval := 1000; MonitoredItemArguments1 := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments1.EndpointDescriptor.UrlString := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; MonitoredItemArguments1.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10845'; MonitoredItemArguments1.MonitoringParameters := MonitoringParameters; MonitoredItemArguments1.SetState(INT_PTR(CustomObject1)); // A custom object that corresponds to the subscription MonitoredItemArguments2 := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments2.EndpointDescriptor.UrlString := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; MonitoredItemArguments2.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10853'; MonitoredItemArguments2.MonitoringParameters := MonitoringParameters; MonitoredItemArguments2.SetState(INT_PTR(CustomObject2)); // A custom object that corresponds to the subscription MonitoredItemArguments3 := CoEasyUAMonitoredItemArguments.Create; MonitoredItemArguments3.EndpointDescriptor.UrlString := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; MonitoredItemArguments3.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10855'; MonitoredItemArguments3.MonitoringParameters := MonitoringParameters; MonitoredItemArguments3.SetState(INT_PTR(CustomObject3)); // A custom object that corresponds to the subscription Arguments := VarArrayCreate([0, 2], varVariant); Arguments[0] := MonitoredItemArguments1; Arguments[1] := MonitoredItemArguments2; Arguments[2] := MonitoredItemArguments3; TVarData(HandleArray).VType := varArray or varVariant; TVarData(HandleArray).VArray := PVarArray( Client.SubscribeMultipleMonitoredItems(Arguments)); for I := VarArrayLowBound(HandleArray, 1) to VarArrayHighBound(HandleArray, 1) do begin Handle := Cardinal(HandleArray[I]); WriteLn('HandleArray[', I, ']: ', Handle); end; WriteLn('Processing monitored item changed events for 10 seconds...'); PumpSleep(10*1000); WriteLn('Unsubscribing...'); Client.UnsubscribeAllMonitoredItems; WriteLn('Waiting for 5 seconds...'); Sleep(5*1000); WriteLn('Finished.'); VarClear(HandleArray); VarClear(Arguments); FreeAndNil(Client); FreeAndNil(ClientEventHandlers); FreeAndNil(CustomObject1); FreeAndNil(CustomObject2); FreeAndNil(CustomObject3); end;
Copyright © 2004-2023 CODE Consulting and Development, s.r.o., Plzen. All rights reserved. Web page: www.opclabs.com
Send Documentation Feedback. Resources: Knowledge Base. Technical support: Online Forums, FAQ.